﻿// <copyright file="Point.cs" company="ALCPU">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Arthur Liberman</author>
// <email>Arthur_Liberman@hotmail.com</email>
// <date>03-30-2010</date>
// <summary>Contains Point structure definition.</summary>

namespace ChessDefinitions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Point structure
    /// </summary>
    public struct Position
    {
        /// <summary>
        /// The X value of the position
        /// </summary>
        private int x;
        
        /// <summary>
        /// The Y value of the position
        /// </summary>
        private int y;

        /// <summary>
        /// Initializes a new instance of the <see cref="Position"/> struct.
        /// </summary>
        /// <param name="x">The X parameter.</param>
        /// <param name="y">The Y parameter.</param>
        public Position(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Position"/> struct. Copy constructor.
        /// </summary>
        /// <param name="pt">The source position.</param>
        public Position(Position pt)
        {
            this.x = pt.X;
            this.y = pt.Y;
        }

        /// <summary>
        /// Gets or sets the X.
        /// </summary>
        /// <value>The X value.</value>
        public int X
        {
            get { return this.x; }
            set { this.x = value; }
        }

        /// <summary>
        /// Gets or sets the Y.
        /// </summary>
        /// <value>The Y value.</value>
        public int Y
        {
            get { return this.y; }
            set { this.y = value; }
        }

        /// <summary>
        /// Calculates the distance between <paramref name="position1"/> and <paramref name="position2"/>.
        /// </summary>
        /// <param name="position1">The first position.</param>
        /// <param name="position2">The second position.</param>
        /// <returns>The distance between the two positions.</returns>
        public static double DistanceBetweenPositions(Position position1, Position position2)
        {
            return Math.Sqrt(
                Math.Pow((position1.X - position2.X), 2) +
                Math.Pow((position1.Y - position2.Y), 2));
        }

        #region Operator overloadings

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="left">The left side operand.</param>
        /// <param name="right">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(Position left, Position right)
        {
            return left.X == right.X && left.Y == right.Y;
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="left">The left side operand.</param>
        /// <param name="right">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(Position left, Position right)
        {
            return !(left == right);
        }

        /// <summary>
        /// Implements the operator +.
        /// </summary>
        /// <param name="left">The left side operand.</param>
        /// <param name="right">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator +(Position left, Position right)
        {
            return new Position(left.X + right.X, left.Y + right.Y);
        }

        /// <summary>
        /// Implements the operator -.
        /// </summary>
        /// <param name="left">The left side operand.</param>
        /// <param name="right">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator -(Position left, Position right)
        {
            return new Position(left.X - right.X, left.Y - right.Y);
        }

        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="a">The left side operand.</param>
        /// <param name="position">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator /(int a, Position position)
        {
            return new Position(position.X / a, position.Y / a);
        }

        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="position">The left side operand.</param>
        /// <param name="a">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator /(Position position, int a)
        {
            return a / position;
        }

        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="a">The left side operand.</param>
        /// <param name="position">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator *(int a, Position position)
        {
            return new Position(position.X * a, position.Y * a);
        }

        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="position">The left side operand.</param>
        /// <param name="a">The right side operand.</param>
        /// <returns>The result of the operator.</returns>
        public static Position operator *(Position position, int a)
        {
            return a * position;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///     <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            bool ret = false;

            if (obj is Position)
            {
                Position pt = (Position)obj;
                ret = this == pt;
            }

            return ret;
        }

        #endregion

        /// <summary>
        /// Calculates the distance between this position and <paramref name="position"/>.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <returns>The distance between the two positions.</returns>
        public double DistanceFromPosition(Position position)
        {
            return Math.Sqrt(
                Math.Pow((this.X - position.X), 2) +
                Math.Pow((this.Y - position.Y), 2));
        }
    }
}
